package control;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */


import entities.tools.Form;
import entities.tools.Question;
import entities.users.FormSigner;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import util.ejb.FormBeanInterface;
import util.ejb.FormFillingBeanInterface;
import util.ejb.FormSignerBeanInterface;

/**
 *
 * @author Marek
 */
@WebServlet(name = "actionReceiveForm", urlPatterns = {"/actionReceiveForm"})
public class actionReceiveForm  extends AbstractServlet {

    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException  {
        response.setContentType("text/html;charset=UTF-8");
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        try (PrintWriter out = response.getWriter()) {
            HttpSession session = request.getSession(true);
            if(session.isNew()){
                //TODO: This is not ok. Client louses his session becouse of timeout, and than he send form again and see white screen, and all of his work is lost. It should by work differently. New session with all session vars should be created, and form request should be serviced normally
                return;
            }
            HashMap<String, String> errorMessages = new HashMap<>();
            HashMap<String, String[]> questionValues = new HashMap<>();
            Map<String, String[]> parameters = request.getParameterMap();
            Object[] keys = parameters.keySet().toArray();
            for (Object key : keys) {
                out.println(key + " : " + Arrays.toString(parameters.get(key)) + "<br>");
                Object[] parameterValues = parameters.get(key);
                for(int x=0;x<parameterValues.length;x++){
                    parameterValues[x]= new String(((String)parameterValues[x]).getBytes("iso-8859-1"),"UTF-8");
                }
                questionValues.put((String)key,Arrays.copyOf(parameterValues,parameterValues.length, String[].class));
            }
            session.setAttribute("questionValues",questionValues);
            //TODO: Think about changing the method how linkHash, Form, FormSigner atributes are read be servlet. Probably aproach of reading this vars directly from the request parameters is better than reading it from the session
            //TODO: Add code responsible for checking the correctness of the request parameters structure, sended by user
            Long sendedFormId = null;
            sendedFormId = new Long(parameters.get("formId")[0]);
            if (sendedFormId == null) {
                out.println("");
                return;
            }
            Form form = (Form) session.getAttribute("form");
            if (null == form) {
                out.println("");
                return;
            }
            System.out.println("Check:" + form.getId() + ":" + sendedFormId);
            if (form.getId().intValue() != sendedFormId.intValue()) {
                throw new Exception("Form sended by you, is different, than the form registered on server");
            }
            FormSigner formSigner = (FormSigner) session.getAttribute("formSigner");
            if (null == formSigner) {
                out.println("");
                return;
            }
            String linkHash = (String) session.getAttribute("linkHash");

            formFillingBean.beginFillingForm(linkHash);
            List<Question> questions = formBean.getAllQuestions(form);
            for (Question question : questions) {
                //check if sended question exist in the form - is it necessary? or mayby cutting every nonexisting question is better aproach                
                //if question doesn't exist in the form throw new exception
                if (!parameters.containsKey("question-" + question.getId())) {
                    //put information to message
                    errorMessages.put("question-" + question.getId(), "Odpowiedź obowiązkowa.");
                } else {
                    out.println("<br/>question id:" + question.getId());

                    String type = parameters.get("question-" + question.getId() + "-type")[0];

                    //TODO: where in the future, should be set the code responsible for, decoding the answer?
                    if (type.equals("radio")) {
                        //TODO: check if the sendend ansfer is correct
                        //if it is correct save it into entity form
                        //if not, save to session information about bad questionhow/
                        //TODO: how to use bean validation here
                        String value = new String(parameters.get("question-" + question.getId())[0].getBytes("iso-8859-1"),"UTF-8");
                        String answerValue = "";
                        answerValue += value + ",";
                        formFillingBean.answerQuestion(question, answerValue);
                    }
                    if (type.equals("grid")) {
                        String answerValue = "";
                        String[] values = questionValues.get("question-" + question.getId());
                        int countNullValue = 0;
                        for (String value : values) {
                            if (value.equals("null") || value.equals("")) {
                                value = null;
                                countNullValue++;
                            } 
                            answerValue += value + "¶";
                        }
                        if(countNullValue!=0&&countNullValue!=values.length){
                            errorMessages.put("question-" + question.getId(), "Nie wypełniłeś całego wiersza.");
                        } 
                        formFillingBean.answerQuestion(question, answerValue);
                    }

                }
            }
            //check if all questions have been answered. 
            //if not, save to the session information, which question need to be answered. 
            //check if in memory are some errors registered. 
            //if yes, go back to the form
            //if now, send save the form

            session.setAttribute("filledForm",formFillingBean.getFilledForm());
            session.setAttribute("formFillingBean",formFillingBean);
            session.setAttribute("errorMessages", errorMessages);
            if (errorMessages.isEmpty()) {
                formFillingBean.sendForm();
                session.invalidate();
                response.sendRedirect("thankYou.jsp");
            } else {
                //formFillingBean.cancelFormFilling(); //TODO: Correct the method. Now it is deleting FilledForm instance, and this is bad, becouse FilledForm instance is pointing to the link. Method should delete all answers only.
                response.sendRedirect("form.jsp?linkHash=" + linkHash);
            }
        } catch (Exception ex) {
            Logger.getLogger(actionReceiveForm.class.getName()).log(Level.SEVERE, null, ex);
            //formFillingBean.cancelFormFilling();
            //clean up the session
        }

    }
}
